{This object tests Cog RAM in cogs 1 through 7 and displays the results on the Parallax Serial Terminal at 19,200 baud.
 Cog 0 starts this object and then hands off control to the first cog that passed the Cog RAM test.  This new cog tests
 cog 0 to complete the test.}

CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000

  SERIAL_BAUD = 19_200
  ResultSize = 512 
  
VAR
  word  Results[ResultSize]

  long  stack[50]

OBJ
  Ser   :       "Simple_Serial"
  Num   :       "Numbers"

PUB Main : passList | cogNum

  Ser.Init(31, 30, SERIAL_BAUD)                                                 'Initialize Simple Serial
  Num.Init                                                                      'Initialize Numbers     

  waitcnt(clkfreq*2+cnt)                                                        'Wait 2 seconds
  Ser.Tx(0)                                                                     'Clear screen
  Ser.Str(string(13, "----Cog RAM Test----", 13))                               'Show heading                     

  repeat cogNum from 1 to 7                                                     'Test each cog
    passList |= TestCog(CogNum) & (1 << cogNum)

  'find a cog that passed the test to launch the last test into
  repeat cogNum from 1 to 7
    if passList & (1<<cogNum)
      quit

  'launch the last test into a cog that passed
  passList := coginit(cogNum, LastTest(passList), @stack)

  if passList == %1111_1111                                                     'have all cogs passed the test?
    'celebrate, because all cogs passed

  else
    'at least one cog failed, so let the operator know

    
PRI LastTest(passList)

  Ser.Init(31, 30, SERIAL_BAUD)                                                 'Initialize Simple Serial
  Num.Init                                                                      'Initialize Numbers     

  'test the last cog (cog 0)
  passList |= TestCog(0) & 1

  return passList

PRI TestCog(CogNum) : passed | Idx

  Ser.Str(string(13, "COG "))                                                   'Show Cog ID                     
  Ser.Str(Num.ToStr(CogNum, Num#DEC))
  Ser.Str(string(" - "))

  wordfill(@Results, $FFFF, ResultSize)

  coginit(CogNum, @TestCogRAM, @Results)                                        'Launch assembly cog
  waitcnt(80000+cnt)                                                            'Wait for cog launch + task completion
  cogstop(CogNum)                                                               'Stop assembly cog                            

  if Results[0] == $200                                                         'Show results
    Ser.Str(string("Passed"))
    passed := true                                 '  Passed
  else
    Ser.Str(string("***FAILED***", 13, "Register(s): "))                        '  or Failed
    passed := false
    Idx := 0
    if Results[0] == $FFFF                                                      '    Cog never reported?  Problem with RAM code resides in                                                                                  
'     Ser.Str(string("< $"))
      Ser.Str(Num.ToStr(@FirstReg-@TestCogRAM+1, Num#IHEX4))
      Ser.Tx(13)                                                                
    else                                                                        '    Else, cog reported.  Display bad register addresses.
      repeat Idx from 0 to ResultSize-1
'       Ser.Tx("$")
        Ser.Str(Num.ToStr(Results[Idx], Num#IHEX4))
        if (Idx+1 < ResultSize) and (Results[Idx+1] < $200)
          Ser.Tx(",")
        else
          quit
    Ser.Tx(13)
  
DAT
                        org 0

TestCogRAM              mov MRAddr, par                                         'Get Main RAM address
                        mov CRAddr, #FirstReg                                   'Get starting Cog RAM register to test

        :Test           movd :WRPattern, CRAddr                                 'Set write address
                        movd :RDPattern, CRAddr                                 'Set read address
                        mov Value, Pattern                                      'Get first pattern ready
        :WRPattern      mov $000, Value                                         'Write pattern
        :RDPattern      cmp $000, Value                 wz                      'Verify pattern; z = match
              if_nz     jmp #:Error                                             'No match? Error
                        shr Value, #8                   wz                      'Else, shift to next pattern; z = done
              if_nz     jmp #:WRPattern                                         'Loop for all patterns

        :NextRegister   cmp CRAddr, #$1FF               wz                      'Done? z = yes
                        add CRAddr, #1                                          'Ready for next Cog RAM register
              if_nz     jmp #:Test                                              'Not done? loop to test next register
                                                                                'Else, fall into Error (to indicate done)
        :Error          wrword CRAddr, MRAddr                                   'Indicate address ($200 if done)
                        add MRAddr, #2                                          'Increment Main RAM address
              if_nz     jmp #:NextRegister                                      'If should continue, loop to test more registers
                        jmp #$                                                  'Else, wait forever

Pattern       long      $55AA_FF00                                              'Bit exercise pattern
CRAddr        res       1                                                       'Cog RAM Address
MRAddr        res       1                                                       'Main RAM Address
Value         res       1                                                       'Value written                        
FirstReg                                                                        'Symbol pointing to first register to test